//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include "FpsSceneManager.h"

#include "ParticleSystem/IFpsParticleSystemSceneNode.h"
#include "ParticleSystem/CFpsParticleSystemSceneNode.h"

#include "IrrCompileConfig.h"
#include "IVideoDriver.h"
#include "IMaterialRenderer.h"
//#include "CColladaDatabase.h"
#include "CCameraSceneNode.h"
//#include "os.h"



//#include "CColladaMeshSceneNode.h"
//#include "COctTreeTriangleSelector.h"
#include "EMaterialTypes.h"
#include "FpsMaterial.h"
#include "CFPSSceneCollisionManager.h"


using namespace irr;
using namespace core;
using namespace scene;
using namespace video;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define DEBUG_STATISTICS

#ifdef DEBUG_STATISTICS

struct SStats
{
	int CullTests;
	int Culled;

	SStats()
	{
		reset();
	}

	void reset(::irr::io::IAttributes* parameters = 0)
	{
		if (parameters)
		{
			parameters->setAttribute("calls", CullTests);
			parameters->setAttribute("culled", Culled);
		}
		CullTests = Culled = 0;
	}

} Stats;

#endif

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//CFpsSceneManager::CFpsSceneManager(irr::video::IVideoDriver* driver, irr::io::IFileSystem* fs,
//		irr::gui::ICursorControl* cursorControl, irr::scene::IMeshCache* cache,
//		irr::gui::IGUIEnvironment *guiEnvironment) :
//	CSceneManager(driver, fs, cursorControl, cache, guiEnvironment)
//{
//	// create collision manager
//	if (getSceneCollisionManager())
//		getSceneCollisionManager()->drop();
//	
////	getSceneCollisionManager() = new CFPSSceneCollisionManager(this, Driver);
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////! registers a node for rendering it at a specific time.
//
//u32 CFpsSceneManager::registerNodeForRendering(ISceneNode* node,
//											const video::SMaterial* material,
//											void* renderData,
//											E_SCENE_NODE_RENDER_PASS time,
//											const core::vector3df* absPos,
//											int layer)
//{
//	u32 taken = 0;
//
//	switch(time)
//	{
//		// take camera if it doesn't exists
//		case ESNRP_CAMERA:
//		{
//			taken = 1;
//			for ( u32 i = 0; i != CameraList.size(); ++i )
//			{
//				if ( CameraList[i].Node == node )
//				{
//					taken = 0;
//					break;
//				}
//			}
//			if ( taken )
//			{
//				CameraList.push_back(SUnsortedNodeEntry(node, renderData));
//			}
//		}
//		break;
//
//	case ESNRP_LIGHT:
//		// TODO: Point Light culling..
//		// Lighting modell in irrlicht has to be redone..
//		//if (!isCulled(node))
//		{
//			LightList.push_back(SDistanceNodeEntry(node, CamWorldPos, renderData));
//			taken = 1;
//		}
//		break;
//
//	case ESNRP_SKY_BOX:
//		SkyBoxList.push_back(SUnsortedNodeEntry(node, renderData));
//		taken = 1;
//		break;
//
//	case ESNRP_SOLID:
//		if (!isCulled(node))
//		{
//			SolidNodeList2.push_back(SFpsDefaultNodeEntry(node, material, renderData));
//			taken = 1;
//		}
//		break;
//
//	case ESNRP_TRANSPARENT:
//		if (!isCulled(node))
//		{
//			if(material && material->getMaterialTypeParam(2) == FPS_MATERIAL_RENDER_PRIORITY_GROUND_TRANSPARENT)
//			{
//				SolidNodeList2.push_back(SFpsDefaultNodeEntry(node, material, renderData));
//			}
//			else
//			{
//				TransparentNodeList.push_back(STransparentNodeEntry(node,
//																	CamWorldPos,
//																	material,
//																	renderData,
//																	absPos,
//																	layer));
//			}
//			taken = 1;
//		}
//		break;
//
//	case ESNRP_AUTOMATIC:
//		if (!isCulled(node))
//		{
//			taken = 1;
//			if (material && material->getMaterialTypeParam(2) != FPS_MATERIAL_RENDER_PRIORITY_GROUND_TRANSPARENT)
//			{
//				video::IMaterialRenderer* rnd =
//					Driver->getMaterialRenderer(material->getMaterialType());
//				if (rnd && rnd->isTransparent() && !IsTransparentPassRegisteredAsSolid)
//				{
//					TransparentNodeList.push_back(STransparentNodeEntry(node,
//																		CamWorldPos,
//																		material,
//																		renderData,
//																		absPos,
//																		layer));
//					break;
//				}
//			}
//			SolidNodeList2.push_back(SFpsDefaultNodeEntry(node, material, renderData));
//		}
//		break;
//
//	case ESNRP_SHADOW:
//		if (!isCulled(node))
//		{
//			ShadowNodeList.push_back(SUnsortedNodeEntry(node, renderData));
//			taken = 1;
//		}
//		break;
//
//	case ESNRP_COUNT: // ignore this one
//		break;
//	}
//
//#ifdef DEBUG_STATISTICS
//	++Stats.CullTests;
//	if (0 == taken)
//	{
//		++Stats.Culled;
//	}
//#endif
//
//	return taken;
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//bool CFpsSceneManager::RegisterMeshBuffers(irr::scene::ISceneNode* node)
//{
//	GX_ASSERT(node);
//
//	//if(node->getMaterialCount() <= 1)
//	//{
//	//	return false;
//	//}
//
//	if(node->getType() != ESNT_COLLADA_MESH)
//	{
//		return false;
//	}
//
//	CColladaMeshSceneNode*	colladaNode	=	static_cast<CColladaMeshSceneNode*>(node);
//	IColladaMesh*			mesh		=	static_cast<IColladaMesh*>(colladaNode->getMesh());
//
//	if(mesh && mesh->getType() != IColladaMesh::ET_MESH)
//	{
//		return false;
//	}
//
//	return true;
//}
//
////! registers a node for rendering it at a specific time.
//u32 CFpsSceneManager::registerNodeForRendering(ISceneNode* node, E_SCENE_NODE_RENDER_PASS time)
//{
//	u32 taken = 0;
//
//	switch(time)
//	{
//		// take camera if it doesn't exists
//		case ESNRP_CAMERA:
//		{
//			taken = 1;
//			for ( u32 i = 0; i != CameraList.size(); ++i )
//			{
//				if ( CameraList[i] == node )
//				{
//					taken = 0;
//					break;
//				}
//			}
//			if ( taken )
//			{
//				CameraList.push_back(node);
//			}
//		}break;
//
//	case ESNRP_LIGHT:
//		// TODO: Point Light culling..
//		// Lighting modell in irrlicht has to be redone..
//		//if (!isCulled(node))
//		{
//			LightList.push_back(DistanceNodeEntry(node, camWorldPos));
//			taken = 1;
//		}
//		break;
//
//	case ESNRP_SKY_BOX:
//		SkyBoxList.push_back(node);
//		taken = 1;
//		break;
//
//	case ESNRP_SOLID:
//		if (!isCulled(node))
//		{
//			u32 count = node->getMaterialCount();
//
//			if(!RegisterMeshBuffers(node))
//			{
//				SolidNodeList2.push_back(node);
//			}
//			else
//			{
//				CColladaMeshSceneNode*	colladaNode	=	static_cast<CColladaMeshSceneNode*>(node);
//				IColladaMesh*			mesh		=	static_cast<IColladaMesh*>(colladaNode->getMesh());
//
//				for(int i = 0; i < count; i++)
//				{
//					IMeshBuffer* mb = mesh->getMeshBuffer(i);
//
//					void* meshBuffer_PositionPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pPosition;
//					void* meshBuffer_ColorPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pColor0;
//					void* meshBuffer_TexCoordPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pTexCoord0;
//
//					const video::SMaterial& material = colladaNode->isReadOnlyMaterials() ? 
//						mb->getMaterial() : colladaNode->getMaterial(i);
//
//					video::IMaterialRenderer* rnd =
//						Driver->getMaterialRenderer(material.getMaterialType());
//					if (rnd && rnd->isTransparent() && material.getMaterialTypeParam(2) != 1.f)
//					{
//						continue;
//					}
//
//					SolidNodeList2.push_back(FpsDefaultNodeEntry(node, i, meshBuffer_PositionPtr, meshBuffer_ColorPtr, meshBuffer_TexCoordPtr,
//						(void*)material.getTexture(0), (int)material.getMaterialTypeParam(2)));
//
//					if(material.getTexture(0) && material.getTexture(0)->getName().equals_ignore_case("ship_cockpit.tga"))
//					{
//						int tt = 0;
//					}
//				}
//			}
//			taken = 1;
//		}
//		break;
//
//	case ESNRP_TRANSPARENT:
//		if (!isCulled(node))
//		{
//			if(node->getMaterial(0).getMaterialTypeParam(2) != 1.f)
//			{
//				TransparentNodeList2.push_back(TransparentNodeEntry(node, camWorldPos));
//				taken = 1;
//			}
//			else
//			{
//				u32 count = node->getMaterialCount();
//
//				if(!RegisterMeshBuffers(node))
//				{
//					SolidNodeList2.push_back(node);
//				}
//				else
//				{
//					CColladaMeshSceneNode*	colladaNode	=	static_cast<CColladaMeshSceneNode*>(node);
//					IColladaMesh*			mesh		=	static_cast<IColladaMesh*>(colladaNode->getMesh());
//
//					for(int i = 0; i < count; i++)
//					{
//						IMeshBuffer* mb = mesh->getMeshBuffer(i);
//
//						void* meshBuffer_PositionPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pPosition;
//						void* meshBuffer_ColorPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pColor0;
//						void* meshBuffer_TexCoordPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pTexCoord0;
//
//						const video::SMaterial& material = colladaNode->isReadOnlyMaterials() ? 
//							mb->getMaterial() : colladaNode->getMaterial(i);
//
//						SolidNodeList2.push_back(FpsDefaultNodeEntry(node, i, meshBuffer_PositionPtr, meshBuffer_ColorPtr, meshBuffer_TexCoordPtr,
//							(void*)material.getTexture(0), (int)material.getMaterialTypeParam(2)));
//					}
//				}
//			}
//		}
//		break;
//
//	case ESNRP_AUTOMATIC:
//		if (!isCulled(node))
//		{
//			u32 count = node->getMaterialCount();
//
//			taken = 0;
//			for (u32 i=0; i<count; ++i)
//			{
//				video::IMaterialRenderer* rnd =
//					Driver->getMaterialRenderer(node->getMaterial(i).getMaterialType());
//				if (rnd && rnd->isTransparent() && node->getMaterial(i).getMaterialTypeParam(2) != 1.f)
//				{
//					// register as transparent node
//					TransparentNodeEntry e(node, camWorldPos);
//					TransparentNodeList2.push_back(e);
//					taken = 1;
//					break;
//				}
//			}
//
//			// not transparent, register as solid
//			if ( 0 == taken )
//			{
//				if(!RegisterMeshBuffers(node))
//				{
//					SolidNodeList2.push_back(node);
//				}
//				else
//				{
//					CColladaMeshSceneNode*	colladaNode	=	static_cast<CColladaMeshSceneNode*>(node);
//					IColladaMesh*			mesh		=	static_cast<IColladaMesh*>(colladaNode->getMesh());
//
//					for(int i = 0; i < count; i++)
//					{
//						IMeshBuffer* mb = mesh->getMeshBuffer(i);
//
//						void* meshBuffer_PositionPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pPosition;
//						void* meshBuffer_ColorPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pColor0;
//						void* meshBuffer_TexCoordPtr = (void*)((const S3DVertexComponentArrays *)mb->getVertices())->pTexCoord0;
//
//						const video::SMaterial& material = colladaNode->isReadOnlyMaterials() ? 
//							mb->getMaterial() : colladaNode->getMaterial(i);
//
//						SolidNodeList2.push_back(FpsDefaultNodeEntry(node, i, meshBuffer_PositionPtr, meshBuffer_ColorPtr, meshBuffer_TexCoordPtr,
//							(void*)material.getTexture(0), (int)material.getMaterialTypeParam(2)));
//					}
//				}
//				taken = 1;
//			}
//		}
//		break;
//
//	case ESNRP_SHADOW:
//		if (!isCulled(node))
//		{
//			ShadowNodeList.push_back(node);
//			taken = 1;
//		}
//		break;
//
//	case ESNRP_COUNT: // ignore this one
//		break;
//	}
//
//#ifdef DEBUG_STATISTICS
//	++Stats.CullTests;
//	if (0 == taken)
//	{
//		++Stats.Culled;
//	}
//#endif
//
//	return taken;
//}
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//! This method is called just before the rendering process of the whole scene.
//! draws all scene nodes
//void CFpsSceneManager::drawAll(ISceneNode* root)
//{
//	video::IVideoDriver* driver = getVideoDriver();
//	if (!driver)
//		return;
//
//	// reset attributes
//// 	Parameters.setAttribute ( "culled", (s32)0 );
////	Parameters.setAttribute ( "calls", (s32)0 );
//	Parameters.setAttribute ( "drawn", (s32)0 );
//// 	Parameters.setAttribute ( "bindings", (s32)0 );
//// 	Parameters.setAttribute ( "drawcalls", (s32)0 );
//
//	// reset all transforms
////#endif
//
//#ifdef _IRR_IDENTITY_MATRIX_INITIALIZATION_PER_FRAME_
//	driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_0, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_1, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_2, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_3, core::IdentityMatrix );
//#endif
//
//	driver->setOption(video::EVDO_ALLOW_ZWRITE_ON_TRANSPARENT,
//					  Parameters.getAttributeAsBool( ALLOW_ZWRITE_ON_TRANSPARENT) );
//
//#ifdef _IRR_ENABLE_SCENE_OPTIMIZED_TRAVERSAL
//	if (HierarchyChanged)
//	{
//		collectAllNodes();
//	}
//#endif // _IRR_ENABLE_SCENE_OPTIMIZED_TRAVERSAL
//
//	/*!
//		First Scene Node for prerendering should be the active camera
//		consistent Camera is needed for culling
//	*/
//	CamWorldPos.set(0,0,0);
//	if (ActiveCamera)
//	{
//		ActiveCamera->OnRegisterSceneNode();
//		CamWorldPos = ActiveCamera->getAbsolutePosition();
//	}
//
//	// let all nodes register themselves
//	(root ? root : this)->OnRegisterSceneNode();
//
//	u32 i; // new ISO for scoping problem in some compilers
//
//	//render camera scenes
//	{
//		CurrentRendertime = ESNRP_CAMERA;
//		for (i=0; i<CameraList.size(); ++i)
//			CameraList[i].Node->render(CameraList[i].RenderData);
//
//		CameraList.set_used(0);
//	}
//
//	//render lights scenes
//	{
//		CurrentRendertime = ESNRP_LIGHT;
//
//		driver->deleteAllDynamicLights();
//
//		driver->setAmbientLight(AmbientLight);
//
//		LightList.sort();		// on distance to camera
//
//		u32 maxLights = core::min_ ( driver->getMaximalDynamicLightAmount(), LightList.size() );
//		for (i=0; i< maxLights; ++i)
//			LightList[i].Node->render(LightList[i].RenderData);
//
//		LightList.set_used(0);
//	}
//
//	// render skyboxes
//	{
//		CurrentRendertime = ESNRP_SKY_BOX;
//
//		
//		for (i=0; i < SkyBoxList.size() && i < 1  ; ++i)
//		{
//			SkyBoxList[i].Node->render(SkyBoxList[i].RenderData);
//		}
//
//		SkyBoxList.set_used(0);
//	}
//
//
//	// render default objects
//	{
//		Driver->setOption(video::EVDO_RETAIN_BATCH_ON_MISS, true);
//
//		CurrentRendertime = ESNRP_SOLID;
//		SolidNodeList2.sort(); // sort by textures
//
//		for (i=0; i<SolidNodeList2.size(); ++i)
//		{
//			if(SolidNodeList2[i].Material->getMaterialTypeParam(2) == FPS_MATERIAL_RENDER_PRIORITY_GROUND_TRANSPARENT)
//			{
//				CurrentRendertime = ESNRP_TRANSPARENT;
//			}
//
//			SolidNodeList2[i].Node->render(SolidNodeList2[i].RenderData);
//
//			CurrentRendertime = ESNRP_SOLID;
//		}
//
//		Parameters.setAttribute ( "drawn", (s32) SolidNodeList2.size() );
//
//		SolidNodeList2.set_used(0);
//
//		Driver->setOption(video::EVDO_RETAIN_BATCH_ON_MISS, false);
//	}
//
//	// render shadows
//	{
//		CurrentRendertime = ESNRP_SHADOW;
//		for (i=0; i<ShadowNodeList.size(); ++i)
//			ShadowNodeList[i].Node->render(ShadowNodeList[i].RenderData);
//
//		if (!ShadowNodeList.empty())
//			driver->drawStencilShadow(true,ShadowColor, ShadowColor,
//				ShadowColor, ShadowColor);
//
//		ShadowNodeList.set_used(0);
//	}
//
//	// render transparent objects.
//	{
//		CurrentRendertime = ESNRP_TRANSPARENT;
//		TransparentNodeList.sort(); // sort by distance from camera
//
//		for (i=0; i<TransparentNodeList.size(); ++i)
//			TransparentNodeList[i].Node->render(TransparentNodeList[i].RenderData);
//
//		TransparentNodeList.set_used(0);
//	}
//
//	clearDeletionList();
//
//	CurrentRendertime = ESNRP_COUNT;
//
//#ifdef DEBUG_STATISTICS
//	// Write and reset stats
//	Stats.reset(&Parameters);
//#endif
//}
//	video::IVideoDriver* driver = getVideoDriver();
//	if (!driver)
//		return;
//
//#if USE_TIME_PROFILE
//	long t0 = os::Timer::getRealTime(), t1, t2, t3, t4, t5, t6, t7, t8;
//#endif //USE_TIME_PROFILE
//
//	// reset attributes
//	Parameters.setAttribute ( "drawn", (s32)0 );
//
//	// reset all transforms
//#ifdef _IRR_IDENTITY_MATRIX_INITIALIZATION_PER_FRAME_
//	driver->setTransform ( video::ETS_PROJECTION, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_VIEW, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_WORLD, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_0, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_1, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_2, core::IdentityMatrix );
//	driver->setTransform ( video::ETS_TEXTURE_3, core::IdentityMatrix );
//#endif
//
//	driver->setAllowZWriteOnTransparent(Parameters.getAttributeAsBool( ALLOW_ZWRITE_ON_TRANSPARENT) );
//	
//
//	/*!
//		First Scene Node for prerendering should be the active camera
//		consistent Camera is needed for culling
//	*/
//	camWorldPos.set(0,0,0);
//	if ( ActiveCamera )
//	{
//		ActiveCamera->OnRegisterSceneNode();
//		camWorldPos = ActiveCamera->getAbsolutePosition();
//
//		if(CLevel::GetLevel())
//		{
//			CLevel::GetLevel()->UpdateRenderingMap();
//		}
//	}
//
//	// let all nodes register themselves
//	OnRegisterSceneNode();
//
//	// level dependent
//	//if(CLevel::GetLevel())
//	//{
//	//	CRoom* pRoom2 = CLevel::GetLevel()->GetPlayer()->GetSecondaryRoom();
//	//	if(pRoom2)
//	//	{
//	//		pRoom2->GetRoomRefNode()->OnRegisterSceneNode();
//	//	}
//	//}
//
//#if USE_TIME_PROFILE
//	t1 = os::Timer::getRealTime();
//#endif //USE_TIME_PROFILE
//
//	u32 i; // new ISO for scoping problem in some compilers
//
//	//render camera scenes
//	{
//		CurrentRendertime = ESNRP_CAMERA;
//		for (i=0; i<CameraList.size(); ++i)
//			CameraList[i]->render();
//
//		CameraList.set_used(0);
//	}
//
//	//render lights scenes
//	if(0)
//	{
//		CurrentRendertime = ESNRP_LIGHT;
//
//		driver->deleteAllDynamicLights();
//
//		driver->setAmbientLight(AmbientLight);
//
//		LightList.sort();		// on distance to camera
//
//		u32 maxLights = core::min_ ( driver->getMaximalDynamicLightAmount(), LightList.size() );
//		for (i=0; i< maxLights; ++i)
//			LightList[i].Node->render();
//
//		LightList.set_used(0);
//	}
//
//	// render skyboxes
//	{
//		CurrentRendertime = ESNRP_SKY_BOX;
//
//		for (i=0; i < SkyBoxList.size() && i < 1; ++i) // allow only a skybox
//			SkyBoxList[i]->render();
//
//		SkyBoxList.set_used(0);
//	}
//
//	Stats.Materials = 2;
//
//#if USE_TIME_PROFILE
//	 t2 = os::Timer::getRealTime();
//#endif //USE_TIME_PROFILE
//
//
//	 const static bool bUseBatching = !true;
//
//	scene::IMeshBuffer*		pBatchingMeshBuffer	=	0;
//	video::SMaterial const*	pBatchingMaterial	=	0;
//	m_nBatchingIndicesOff						=	0;
//
//	matrix4 mm4;
//
//	video::SMaterial* pLastMaterial = 0;
//
//	int stats_drawsNodes = 0;
//	int stats_drawsBatches = 0;
//
//	// render default objects
//	{
//		CurrentRendertime = ESNRP_SOLID;
//		SolidNodeList2.sort(); // sort by textures
//
//#if USE_TIME_PROFILE
//		t3 = os::Timer::getRealTime();
//#endif //USE_TIME_PROFILE
//
//		//DEBUG_OUT("SOLID SIZE: %d\n", SolidNodeList2.size());
//
//		ISceneNode* pLastRendedNode = 0;
//		for (i=0; i<SolidNodeList2.size(); ++i)
//		{
//			if(SolidNodeList2[i].meshBufferIndex == -1)
//			{
//				// flush batching
//				if(bUseBatching)
//				{
//					if(pBatchingMeshBuffer)
//					{
//						//DEBUG_OUT("SET MATERIAL - F1(%d) - %s\n", i, pBatchingMaterial->getTexture(0)->getName().c_str());
//						getVideoDriver()->setMaterial(*pBatchingMaterial);
//						getVideoDriver()->drawVertexPrimitiveList(pBatchingMeshBuffer->getVertices(), 
//																	pBatchingMeshBuffer->getVertexCount(),
//																	m_aBatchingIndices,
//																	m_nBatchingIndicesOff / 3,
//																	pBatchingMeshBuffer->getVertexType(),
//																	scene::EPT_TRIANGLES, 
//																	pBatchingMeshBuffer->getIndexType()
//																	);
//						//DEBUG_OUT("FLUSH %d\n", m_nBatchingIndicesOff);
//						GX_ASSERT((m_nBatchingIndicesOff % 3)==0);
//						pBatchingMeshBuffer = 0;
//						stats_drawsBatches++;
//					}
//				}
//
//				if(SolidNodeList2[i].Node->getMaterial(0).getMaterialTypeParam(2) == 1.f)
//				{
//					CurrentRendertime = ESNRP_TRANSPARENT;
//				}
//				else
//				{
//					CurrentRendertime = ESNRP_SOLID;
//				}
//
//				//DEBUG_OUT("SET MATERIAL(%d) - %s\n", i, SolidNodeList2[i].Node->getMaterial(0).getTexture(0)->getName().c_str());
//
//				stats_drawsNodes++;
//				SolidNodeList2[i].Node->render();
//				pLastMaterial = 0;
//			}
//			else
//			{
//				const int mbIndex = SolidNodeList2[i].meshBufferIndex;
//				CColladaMeshSceneNode* meshNode = (CColladaMeshSceneNode*)SolidNodeList2[i].Node;
//				scene::IMeshBuffer* mb = meshNode->getMesh()->getMeshBuffer(mbIndex);
//
//				const video::SMaterial& material = meshNode->isReadOnlyMaterials() ? 
//					mb->getMaterial() : meshNode->getMaterial(mbIndex);
//
//				const matrix4& mat = meshNode->getRelativeTransformation();
//
//
//				if(bUseBatching)
//				{
//					if(pBatchingMeshBuffer)
//					{
//						bool bFlush = false;
//
//						if(*pBatchingMaterial != material)
//						{
//							bFlush = true;
//						}
//						else if(meshNode->getGameData() != (void*)1) // gamedata is 1 for static geometry
//						{
//							bFlush = true;
//						}
//						else
//						{
//							const S3DVertexComponentArrays *pOldVertices = (const S3DVertexComponentArrays *)pBatchingMeshBuffer->getVertices();
//							const S3DVertexComponentArrays *pNewVertices = (const S3DVertexComponentArrays *)mb->getVertices();
//
//							if(pOldVertices->pPosition		!=	pNewVertices->pPosition || 
//								pOldVertices->pColor0		!=	pNewVertices->pColor0 || 
//								pOldVertices->pTexCoord0	!=	pNewVertices->pTexCoord0)
//							{
//								bFlush = true;
//							}
//						}
//
//						if(bFlush)
//						{
//							//DEBUG_OUT("SET MATERIAL - F2(%d) - %s\n", i, pBatchingMaterial->getTexture(0)->getName().c_str());
//							getVideoDriver()->setMaterial(*pBatchingMaterial);
//							getVideoDriver()->drawVertexPrimitiveList(pBatchingMeshBuffer->getVertices(), 
//																		pBatchingMeshBuffer->getVertexCount(),
//																		m_aBatchingIndices,
//																		m_nBatchingIndicesOff / 3,
//																		pBatchingMeshBuffer->getVertexType(),
//																		scene::EPT_TRIANGLES, 
//																		pBatchingMeshBuffer->getIndexType()
//																		);
//							//DEBUG_OUT("FLUSH %d\n", m_nBatchingIndicesOff);
//							GX_ASSERT((m_nBatchingIndicesOff % 3)==0);
//							stats_drawsBatches++;
//							pBatchingMeshBuffer = 0;
//						}
//						else
//						{
//							//pBatchingMaterial		=	&material;
//							if(mm4 != meshNode->getAbsoluteTransformation())
//							{
//								int trtr=0;
//							}
//							//DEBUG_OUT("Batch node: %s, mb=%d\n", meshNode->getName(), mbIndex);
//							memcpy(&m_aBatchingIndices[m_nBatchingIndicesOff], mb->getIndices(), mb->getIndexCount() * sizeof(u16));
//							m_nBatchingIndicesOff += mb->getIndexCount();
//							continue;
//						}
//					}
//					
//					{
//						getVideoDriver()->setTransform(video::ETS_WORLD, meshNode->getAbsoluteTransformation());
//						mm4 = meshNode->getAbsoluteTransformation();
//					}
//
//					m_nBatchingIndicesOff	=	0;
//
//					if(meshNode->getGameData() != (void*)1) // gamedata is 1 for static geometry
//					{
//						//DEBUG_OUT("Draw node: %s - %s, mb=%d\n", meshNode->getName(), meshNode->getParent()->getName(), mbIndex);
//						getVideoDriver()->setMaterial(material);
//						getVideoDriver()->drawMeshBuffer(mb);
//					}
//					else
//					{
//						pBatchingMeshBuffer		=	mb;
//						pBatchingMaterial		=	&material;
//
//						//DEBUG_OUT("Start Batch node: %s, mb=%d\n", meshNode->getName(), mbIndex);
//						memcpy(&m_aBatchingIndices[m_nBatchingIndicesOff], mb->getIndices(), mb->getIndexCount() * sizeof(u16));
//						m_nBatchingIndicesOff += mb->getIndexCount();
//					}
//				}
//				else
//				{
//					if(pLastRendedNode != meshNode)
//					{
//						getVideoDriver()->setTransform(video::ETS_WORLD, meshNode->getAbsoluteTransformation());
//					}
//
//					{
//						getVideoDriver()->setMaterial(material);
//						getVideoDriver()->drawMeshBuffer(mb);
//					}
//
//				}
//			}
//
//			pLastRendedNode = SolidNodeList2[i].Node;
//		}
//
//		// flush batching
//		if(bUseBatching)
//		{
//			if(pBatchingMeshBuffer)
//			{
//				//DEBUG_OUT("SET MATERIAL - FF(%d) - %s\n", i, pBatchingMaterial->getTexture(0)->getName().c_str());
//				getVideoDriver()->setMaterial(*pBatchingMaterial);
//				getVideoDriver()->drawVertexPrimitiveList(pBatchingMeshBuffer->getVertices(), 
//															pBatchingMeshBuffer->getVertexCount(),
//															m_aBatchingIndices,
//															m_nBatchingIndicesOff / 3,
//															pBatchingMeshBuffer->getVertexType(),
//															scene::EPT_TRIANGLES, 
//															pBatchingMeshBuffer->getIndexType()
//															);
//				stats_drawsBatches++;
//				pBatchingMeshBuffer = 0;
//			}
//		}
//
//		//DEBUG_OUT("stats_drawsNodes = %d, stats_drawsBatches = %d\n", stats_drawsNodes, stats_drawsBatches);
//
//		Parameters.setAttribute ( "drawn", (s32) SolidNodeList2.size() );
//
//		SolidNodeList2.set_used(0);
//	}
//
//#if USE_TIME_PROFILE
//	 t4 = os::Timer::getRealTime();
//#endif //USE_TIME_PROFILE
//
//	// render shadows
//	if(0)
//	{
//		CurrentRendertime = ESNRP_SHADOW;
//		for (i=0; i<ShadowNodeList.size(); ++i)
//			ShadowNodeList[i]->render();
//
//		if (!ShadowNodeList.empty())
//			driver->drawStencilShadow(true,ShadowColor, ShadowColor,
//				ShadowColor, ShadowColor);
//
//		ShadowNodeList.set_used(0);
//	}
//
//	pLastMaterial = 0;
//
//	// render transparent objects.
//	{
//		CurrentRendertime = ESNRP_TRANSPARENT;
//		TransparentNodeList2.sort(); // sort by distance from camera
//	// t5 = os::Timer::getRealTime();
//		for (i=0; i<TransparentNodeList2.size(); ++i)
//		{
//			TransparentNodeList2[i].Node->render();
//
//			Stats.MaterialsT += TransparentNodeList2[i].Node->getMaterialCount();
//		}
//
//		TransparentNodeList2.set_used(0);
//	}
//
//#if USE_TIME_PROFILE
//	t6 = os::Timer::getRealTime();
//#endif //USE_TIME_PROFILE
//
//	clearDeletionList();
//
//	CurrentRendertime = ESNRP_COUNT;
//
//#ifdef DEBUG_STATISTICS
//	// Write and reset stats
//	Stats.reset(&Parameters);
//#endif
//
//#if USE_TIME_PROFILE
//	 t7 = os::Timer::getRealTime();
//
//	// glFlush();
//	 t8 = os::Timer::getRealTime();
//
//	 t_d_register = t1 - t0;
//	 t_d_skybox = t2 - t1;
//	 t_d_sort = t3 - t2;
//	 t_d_solid = t4 - t3;
//	 t_d_trans = t6 - t4;
//	 t_d_flush = t8 - t6;
//#endif //USE_TIME_PROFILE
//
//	//printf("%d - %d - %d - %d - %d - %d\n", t1 - t0, t2 - t1, t3 - t2, t4 - t3, t5 - t4, t6 - t5, t7 - t6);
//
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


//void CFpsSceneManager::clearRenderLists()
//{
//	CameraList.set_used(0);
//	SkyBoxList.set_used(0);
//	LightList.set_used(0);
//	SolidNodeList2.set_used(0);
//	TransparentNodeList.set_used(0);
//}
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////! Adds a particle system scene node.
//
//IFpsParticleSystemSceneNode* CFpsSceneManager::addFpsParticleSystemSceneNode(
//	bool withDefaultEmitter, ISceneNode* parent, s32 id,
//	const core::vector3df& position, const core::vector3df& rotation,
//	const core::vector3df& scale)
//{
//	if (!parent)
//		parent = this;
//
//	IFpsParticleSystemSceneNode* node = new CFpsParticleSystemSceneNode(withDefaultEmitter,
//		id, position, rotation, scale);
//	parent->addChild(node);
//
//	node->drop();
//
//	return node;
//}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
